package top.techqi.app.mcs51.usbdlk

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Rect
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.RECEIVER_EXPORTED
import androidx.core.util.forEach
import androidx.core.util.isEmpty
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.RecyclerView
import top.techqi.app.mcs51.R
import top.techqi.app.mcs51.const.ACTION_USB_PERMISSION
import top.techqi.app.mcs51.const.EXTRA_PENDING_INTF_ID
import top.techqi.app.mcs51.databinding.FragmentUsbdlkListBinding
import top.techqi.app.mcs51.usbdlk.tile.UsbdlkListHeadPortion
import top.techqi.app.mcs51.usbdlk.tile.UsbdlkListNonePortion
import top.techqi.app.mcs51.usbdlk.tile.UsbdlkListPortPortion
import top.techqi.app.mcs51.usbdlk.tile.UsbdlkListTailPortion
import top.techqi.app.mcs51.usbdlk.tile.UsbdlkListUsbdPortion
import top.techqi.app.mcs51.usbdlk.vm.UsbdlkViewModel
import top.techqi.core.base.BaseFragment
import top.techqi.core.util.ResUtil
import top.techqi.usbd.UsbProber
import top.techqi.view.recyclerview.tile.TileAdapter

class UsbdlkListFragment : BaseFragment<FragmentUsbdlkListBinding>(
    FragmentUsbdlkListBinding::inflate
), UsbdlkListPortPortion.Interaction {
    private val vmUsbdlk by viewModels<UsbdlkViewModel>(ownerProducer = { requireParentFragment() })

    private val usbReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                ACTION_USB_PERMISSION -> {
                    val granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                    if (granted) {
                        @Suppress("DEPRECATION")
                        val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
                        val intfId = intent.getIntExtra(EXTRA_PENDING_INTF_ID, -1)
                        if (device != null && intfId >= 0) {
                            vmUsbdlk.openDevice(device, intfId)
                        }
                    }
                }
            }
        }
    }

    private val tileAdapter = TileAdapter()

    override fun onAttach(context: Context) {
        super.onAttach(context)

        val filter = IntentFilter()
        filter.addAction(ACTION_USB_PERMISSION)
        ContextCompat.registerReceiver(context, usbReceiver, filter, RECEIVER_EXPORTED)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        tileAdapter.register(UsbdlkListHeadPortion())
        tileAdapter.register(UsbdlkListTailPortion())
        tileAdapter.register(UsbdlkListUsbdPortion())
        tileAdapter.register(UsbdlkListNonePortion())
        tileAdapter.register(UsbdlkListPortPortion(this))
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.rccUsbdlkList.adapter = tileAdapter
        binding.rccUsbdlkList.addItemDecoration(object : RecyclerView.ItemDecoration() {
            override fun getItemOffsets(
                outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
            ) {
                val space = ResUtil.getDimensionPixelSize(R.dimen.main_usbdlk_list_card_margin)
                outRect.left = space
                outRect.right = space
                val holder = parent.getChildViewHolder(view)
                when (holder) {
                    is UsbdlkListHeadPortion.Holder -> outRect.top = space / 2
                    is UsbdlkListTailPortion.Holder -> outRect.bottom = space / 2
                }
            }
        })

        vmUsbdlk.devicesData.observe(viewLifecycleOwner) { transformData(it) }
    }

    override fun onDetach() {
        context?.unregisterReceiver(usbReceiver)
        super.onDetach()
    }

    override fun onUartClick(record: UsbdlkListPortPortion.Record) {
        val device = record.device
        if (!vmUsbdlk.hasPermission(device)) {
            vmUsbdlk.reqPermission(device, record.intfId)
        } else {
            vmUsbdlk.openDevice(device, record.intfId)
        }
    }

    private fun transformData(list: List<UsbDevice>) {
        val data = list.flatMap { item ->
            val temp = mutableListOf(
                UsbdlkListHeadPortion.Record(item.deviceName),
                UsbdlkListTailPortion.Record(item.deviceName),
            )
            temp.add(
                temp.lastIndex,
                UsbdlkListUsbdPortion.Record(
                    item.deviceName,
                    item.vendorId,
                    item.productId,
                    item.manufacturerName?.trim(),
                    item.productName?.trim(),
                    item
                )
            )
            val drivers = UsbProber.detectDrivers(item)
            if (drivers.isEmpty()) {
                temp.add(
                    temp.lastIndex,
                    UsbdlkListNonePortion.Record(item.deviceName)
                )
            } else {
                drivers.forEach { key, value ->
                    temp.add(
                        temp.lastIndex,
                        UsbdlkListPortPortion.Record(item, value.second, key, value.first)
                    )
                }
            }
            temp
        }
        tileAdapter.commit(data)
    }

    companion object {
        const val TAG = "UsbdlkListFragment"
    }
}
